package com.example.myapp;

import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

/**
 * Created by 艳双 on 2015/12/21.
 * project:TakePhoto
 * user:lisa[FR]
 * Date:2015/12/21
 */
public class UploadUtil {
    private static final String BOUNDARY = UUID.randomUUID().toString(); // ????????????
    // ????????????
    private static final String PREFIX = "--";
    private static final String LINE_END = "\r\n";
    private static final String CONTENT_TYPE = "multipart/form-data"; // ????????????

    private static final String TAG = "UploadUtil";
    private int readTimeOut = 30 * 1000; // ????????????
    private int connectTimeout = 30 * 1000; // ????????????
    /***
     * ????????????????????????
     */
    private int requestTime = 0;

    private String CHARSET = "GBK"; // ????????????

    /***
     * ????????????
     */
    public final int UPLOAD_SUCCESS_CODE = 1;
    /**
     * ???????????????
     */
    public final int UPLOAD_FILE_NOT_EXISTS_CODE = 2;
    /**
     * ???????????????
     */
    public static final int UPLOAD_SERVER_ERROR_CODE = 3;
    protected static final int WHAT_TO_UPLOAD = 1;
    protected static final int WHAT_UPLOAD_DONE = 2;

    /**
     * android????????????????????????
     *
     * @param filePath
     *            ??????????????????????????????
     * @param fileKey
     *            ????????????<input type=file name=xxx/> xxx???????????????fileKey
     * @param RequestURL
     *            ?????????URL
     */
    public void uploadFile(String filePath, String fileKey, String RequestURL, Map<String, String> param) {
        if (filePath == null) {
            sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE, "???????????????");
            return;
        }
        try {
            File file = new File(filePath);
            uploadFile(file, fileKey, RequestURL, param);
        } catch (Exception e) {
            sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE, "???????????????");
            e.printStackTrace();
            return;
        }
    }

    /**
     * android????????????????????????
     *
     * @param file
     *            ?????????????????????
     * @param fileKey
     *            ????????????<input type=file name=xxx/> xxx???????????????fileKey
     * @param RequestURL
     *            ?????????URL
     */
    public void uploadFile(final File file, final String fileKey, final String RequestURL,
                           final Map<String, String> param) {
        if (file == null || (!file.exists())) {
            sendMessage(UPLOAD_FILE_NOT_EXISTS_CODE, "???????????????");
            return;
        }

        Log.i(TAG, "?????????URL=" + RequestURL);
        Log.i(TAG, "?????????fileName=" + file.getName());
        Log.i(TAG, "?????????fileKey=" + fileKey);
        new Thread(new Runnable() { // ????????????????????????
            @Override
            public void run() {
                toUploadFile(file, fileKey, RequestURL, param);
            }
        }).start();

    }

    public String toUploadFile(File file, String fileKey, String RequestURL, Map<String, String> param) {
        String result = null;
        requestTime = 0;

        long requestTime = System.currentTimeMillis();
        long responseTime = 0;

        DataOutputStream dos = null;
        InputStream is = null;
        InputStream input = null;
        ByteArrayOutputStream out = null;

        try {
            URL url = new URL(RequestURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(readTimeOut);
            conn.setConnectTimeout(connectTimeout);
            conn.setDoInput(true); // ???????????????
            conn.setDoOutput(true); // ???????????????
            conn.setUseCaches(false); // ?????????????????????
            conn.setRequestMethod("POST"); // ????????????
            conn.setRequestProperty("Charset", CHARSET); // ????????????
            // conn.setRequestProperty("Accept-Charset", CHARSET);
            // conn.setRequestProperty("contentType", CHARSET);
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            // conn.setRequestProperty("Content-Type",
            // "application/x-www-form-urlencoded");

            /**
             * ????????????????????????????????????????????????
             */
            dos = new DataOutputStream(conn.getOutputStream());
            StringBuffer sb = null;
            String params = "";

            /***
             * ???????????????????????????
             */
            if (param != null && param.size() > 0) {
                Iterator<String> it = param.keySet().iterator();
                while (it.hasNext()) {
                    sb = null;
                    sb = new StringBuffer();
                    String key = it.next();
                    String value = param.get(key);
                    sb.append(PREFIX).append(BOUNDARY).append(LINE_END);
                    sb.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(LINE_END)
                            .append(LINE_END);
                    sb.append(value).append(LINE_END);

                    params = sb.toString();
                    Log.i(TAG, key + "=" + params + "##");

                    // params = URLEncoder.encode(params, "GBK");

                    dos.write(params.getBytes("gbk"));
                    // dos.flush();
                }
            }

            sb = null;
            params = null;
            sb = new StringBuffer();
            /**
             * ????????????????????? name?????????????????????????????????key ????????????key ??????????????????????????????
             * filename??????????????????????????????????????? ??????:abc.png
             */
            sb.append(PREFIX).append(BOUNDARY).append(LINE_END);
            sb.append("Content-Disposition:form-data; name=\"" + fileKey + "\"; filename=\"" + file.getName() + "\""
                    + LINE_END);
            sb.append("Content-Type:image/pjpeg" + LINE_END); // ???????????????Content-type????????????
            // ?????????????????????????????????????????????
            sb.append(LINE_END);
            params = sb.toString();
            sb = null;

            Log.i(TAG, file.getName() + "=" + params + "##");
            dos.write(params.getBytes());
            /** ???????????? */
            is = new FileInputStream(file);
            if (onUploadProcessListener != null)
                onUploadProcessListener.initUpload((int) file.length());
            byte[] bytes = new byte[1024];
            int len = 0;
            int curLen = 0;
            while ((len = is.read(bytes)) != -1) {
                curLen += len;
                dos.write(bytes, 0, len);
                if (onUploadProcessListener != null)
                    onUploadProcessListener.onUploadProcess(curLen);
            }

            dos.write(LINE_END.getBytes());
            byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
            dos.write(end_data);
            dos.flush();
            //
            // dos.write(tempOutputStream.toByteArray());
            /**
             * ??????????????? 200=?????? ????????????????????????????????????
             */
            int res = conn.getResponseCode();
            responseTime = System.currentTimeMillis();
            requestTime = (int) ((responseTime - requestTime) / 1000);
            Log.e(TAG, "response code:" + res);
            if (res == 200) {
                Log.e(TAG, "request success");
                input = conn.getInputStream();
                int count = 0;
                byte[] buffer = new byte[1024];
                out = new ByteArrayOutputStream();
                while ((count = input.read(buffer)) != -1) {
                    out.write(buffer, 0, count);
                }
                result = new String(out.toByteArray(), "UTF-8");
                // StringBuffer sb1 = new StringBuffer();
                // int ss;
                // while ((ss = input.read()) != -1) {
                // sb1.append((char) ss);
                // }
                // result = sb1.toString();
                Log.e(TAG, "result: " + result);
                sendMessage(UPLOAD_SUCCESS_CODE, "???????????????" + result);
                return result;
            } else {
                Log.e(TAG, "request error");
                sendMessage(UPLOAD_SERVER_ERROR_CODE, "???????????????code=" + res);
                return null;
            }
        } catch (MalformedURLException e) {
            sendMessage(UPLOAD_SERVER_ERROR_CODE, "???????????????error=" + e.getMessage());
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            sendMessage(UPLOAD_SERVER_ERROR_CODE, "???????????????error=" + e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * ??????????????????
     *
     * @param responseCode
     * @param responseMessage
     */
    private void sendMessage(int responseCode, String responseMessage) {
        if (onUploadProcessListener != null)
            onUploadProcessListener.onUploadDone(responseCode, responseMessage);
    }

    /**
     * ??????????????????????????????????????????????????????????????????????????????
     *
     * @author shimingzheng
     *
     */
    public static interface OnUploadProcessListener {
        /**
         * ????????????
         *
         * @param responseCode
         * @param message
         */
        void onUploadDone(int responseCode, String message);

        /**
         * ?????????
         *
         * @param uploadSize
         */
        void onUploadProcess(int uploadSize);

        /**
         * ????????????
         *
         * @param fileSize
         */
        void initUpload(int fileSize);
    }

    private OnUploadProcessListener onUploadProcessListener;

    public void setOnUploadProcessListener(OnUploadProcessListener onUploadProcessListener) {
        this.onUploadProcessListener = onUploadProcessListener;
    }

    public int getReadTimeOut() {
        return readTimeOut;
    }

    public void setReadTimeOut(int readTimeOut) {
        this.readTimeOut = readTimeOut;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    /**
     * ???????????????????????????
     *
     * @return
     */
    public int getRequestTime() {
        return requestTime;
    }

    public interface uploadProcessListener {

    }

    public void setCharset(String charset) {
        this.CHARSET = charset;
    }
    /**
     * 上传图片
     *
     * @param url
     *            上传的地址
     * @param params
     *            参数
     * @param fileData
     *            图像数据
     * @return
     */
    public static JSONObject uploadIcon(String url,
                                        HashMap<String, String> params, byte[] fileData) {
        JSONObject result = null;
        String BOUNDARY = UUID.randomUUID().toString();
        String PREFIX = "--";
        String LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";
        try {
            URL uri = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
            conn.setReadTimeout(5 * 1000); // 缓存的最长时间
            conn.setDoInput(true);// 允许输入
            conn.setDoOutput(true);// 允许输出
            conn.setUseCaches(false); // 不允许使用缓存
            conn.setRequestMethod("POST");
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA
                    + ";boundary=" + BOUNDARY);
            // ===写入参数
            StringBuilder sb_params = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                sb_params.append(PREFIX);
                sb_params.append(BOUNDARY);
                sb_params.append(LINEND);
                sb_params.append("Content-Disposition: form-data; name=\""
                        + entry.getKey() + "\"" + LINEND);
                sb_params.append("Content-Type: text/plain; charset=" + CHARSET
                        + LINEND);
                sb_params.append("Content-Transfer-Encoding: 8bit" + LINEND);
                sb_params.append(LINEND);
                sb_params.append(entry.getValue());
                sb_params.append(LINEND);
            }
            // ===参数写入完毕=======
            // ===写入文件
            DataOutputStream outStream = new DataOutputStream(
                    conn.getOutputStream());
            outStream.write(sb_params.toString().getBytes());
            StringBuilder sb_file = new StringBuilder();
            sb_file.append(PREFIX);
            sb_file.append(BOUNDARY);
            sb_file.append(LINEND);
            sb_file.append("Content-Disposition: form-data; name=\"file\"; filename=\"deviceIcon.jpg\""
                    + LINEND);
            sb_file.append("Content-Type: application/octet-stream; charset="
                    + CHARSET + LINEND);
            sb_file.append(LINEND);
            outStream.write(sb_file.toString().getBytes());
            outStream.write(fileData, 0, fileData.length);
            outStream.write(LINEND.getBytes());
            // ===文件写入完毕
            byte[] endFlag = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
            outStream.write(endFlag);// 写入文件结尾符
            outStream.flush();
            // =========================
            // 处理响应
            int res = conn.getResponseCode();
            if (res == 200) {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                StringBuilder sb_result = new StringBuilder();
                String tmp = null;
                while ((tmp = reader.readLine()) != null) {
                    sb_result.append(tmp);
                }
                try {
                    result = new JSONObject(sb_result.toString());
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            outStream.close();
            conn.disconnect();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return result;
    }
}
